home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 015 / epsilon.arc / BETTERC.ARC / C.E next >
Encoding:
Text File  |  1986-01-05  |  7.5 KB  |  270 lines

  1. /************************************************************************
  2. * "Epsilon", "EEL" and "Lugaru" are trademarks of Lugaru Software, Ltd. *
  3. *                                    *
  4. *     Copyright (C) 1985 Lugaru Software Ltd.  All rights reserved.    *
  5. *                                    *
  6. * Limited permission is hereby granted to reproduce and modify this    *
  7. * copyrighted material provided that the resulting code is used only in    *
  8. * conjunction with Lugaru products and that this notice is retained in    *
  9. * any such reproduction or modification.                *
  10. ************************************************************************/
  11.  
  12. /*
  13.  *  Modifications copyright (c) 1985 by David Dyer-Bennet
  14.  *  Permission for non-commercial use is hereby granted; all other
  15.  *  rights are reserved.
  16.  *
  17.  *  Modifications by David Dyer-Bennet
  18.  *  Terrabit Software
  19.  *  4242 Minnehaha Ave S
  20.  *  Minneapolis, MN 55406
  21.  *  Sysop of Fido 14/341, The Terraboard, (612) 721-8967 3/12/24 24hrs
  22.  *  (612) 721-8800 NOT 24 hrs!  More like noon to midnight
  23.  */
  24.  
  25. /*
  26.  *  Revision history:
  27.  *
  28.  *      Edit    Date        Who     Description
  29.  *
  30.  *  Version 1.0
  31.  *      0       12-Nov-85   Lugaru  Epsilon Version 3.01
  32.  *      1       3-Jan-86    DD-B    Add support for comment.e
  33.  *    2    4-Jan-86    DD-B    Add error definition for next-error
  34.  *                                  for Microsoft C compiler
  35.  *    3    6-Jan-86    DD-B    Add E mode for eel error definition
  36.  */
  37.  
  38. #include "eel.h"
  39. #include "comment.h"                    /* [1] Global vars */
  40.  
  41. /* [2] Define format of compiler error messages for proc.e */
  42. buffer char *error_recog;
  43. buffer char *erfile_recog;
  44. buffer char *erline_recog;
  45.  
  46. /*
  47. Automatic indentation for C and EEL code.  Several indenting styles
  48. are supported, selected by the following variables.
  49. The position of the closing brace is controlled by the Closeback variable:
  50.  
  51. Closeback = 0;            Closeback = 1;
  52. if (foo) {            if (foo) {
  53.     bar();                bar();
  54.     baz();                baz();
  55.     }            }
  56.  
  57. If Closeback = 0 the following style may also be used:
  58. if (foo)
  59.     {
  60.     bar();
  61.     baz();
  62.     }
  63.  
  64. */
  65. int Closeback = 1;
  66. /*
  67. The Topindent variable controls whether top-level statements in a function
  68. are indented:
  69.  
  70. Topindent = 0;            Topindent = 1;
  71. foo()                foo()
  72. {                {
  73. if (bar)                if (bar)
  74.     baz();                    baz();
  75. }                }
  76. */
  77. int Topindent = 1;
  78.  
  79. /*
  80. The Matchdelim variable controls whether typing ), ], or } displays the
  81. corresponding (, [, or { when the former is typed.  It uses the
  82. show-matching-delimiter command.
  83. */
  84. int Matchdelim = 1;
  85.  
  86.  
  87. keytable c_tab;                            /* key table for c mode */
  88.  
  89. /* by default, the indenting levels are one tab stop apart */
  90. #define INCR    4                        /* [1] */
  91.  
  92. /* define an RE matching C comments or whitespace */
  93. #define C_SKIP "((/%*([^*]|%*[^/])*%*/)|[ \t\n])*"
  94.  
  95. c_indenter()        /* replace surrounding indentation with new */
  96. {
  97.     to_column(c_compute_indent());
  98. }
  99.  
  100. command c_mode()
  101. {
  102.     mode_keys = c_tab;        /* use these keys */
  103.     if (Matchdelim)
  104.         c_tab[')'] = c_tab[']'] = (short) show_matching_delimiter;
  105.     major_mode = strsave("C");
  106.     make_mode();
  107.     indenter = c_indenter;
  108.     auto_indent = 1;
  109.     /* [1] Define C comments for the comment package */
  110.     comment_recog = "((/%* )|(/%*))!(.*)%*/$";
  111.     comment_begin = "/* ";
  112.     comment_end = " */";
  113.     comment_col = 32;
  114.     comment_limit = 60;
  115.     /* [1] end insert */
  116.     /* [2] Show next-error what an error looks like */
  117.     error_recog = "^[a-zA-Z0-9_.%/:]+%([0-9]+%) :.*";
  118.                 /* Microsoft C */
  119.                 /* errors look like: file(line): */
  120.  
  121.     erfile_recog = "([a-zA-Z0-9_.%/:]+)%(";
  122.     erline_recog = "([0-9]+)%)";
  123.     /* [2] End insert */
  124. }
  125.  
  126. /* [3] 
  127.  *  Special "e" mode, which differs from c only in the error finding
  128.  */
  129. command e_mode ()
  130. {
  131.     c_mode ();
  132.     major_mode = strsave("E");
  133.     make_mode ();
  134.     error_recog = "^[a-zA-Z0-9_.%/:]+[ \t]+[0-9]+:";    /* Eel */
  135.     erfile_recog = "([a-zA-Z9-0_.%/:]+)[ \t]+";
  136.     erline_recog = "([0-9]+):";
  137. }                /* end e_mode () */
  138.  
  139. /* make this the default mode for .c, .h, and .e files */
  140. suffix_c()    { c_mode(); }
  141. suffix_h()    { c_mode(); }
  142. suffix_e()    { e_mode(); }
  143.  
  144. /*  Look at the last two lines and return the correct indentation
  145.     for the current line, assuming C source (or similar).  At start,
  146.     we must be at the end of a line's indentation.
  147. */
  148.  
  149. c_compute_indent()
  150. {
  151.     int orig = point, prev_keyword;
  152.     int prev_end = ';', prev2_end = ';';    /* last chr on 2 prev lines */
  153.     int ind = 0;                /* indentation to use */
  154.     int first_char;                /* cur line's first char */
  155.  
  156.     first_char = curchar();
  157.     to_begin_line();
  158.     re_search(-1, C_SKIP);        /* skip whitespace and comments */
  159.     if (point > 0) {
  160.         prev_end = character(--point);    /* get last relevant char */
  161.         to_indentation();
  162.         ind = current_column();    /* and indentation of its line */
  163.         prev_keyword = point;    /* save its position too */
  164.  
  165.         re_search(-1, C_SKIP);    /* skip whitespace and comments */
  166.         if (point > 0)        /* and get last interesting char on */
  167.             prev2_end = character(point-1); /* line before that */
  168.  
  169.         point = prev_keyword;    /* prepare for checking prev line */
  170.     }
  171.  
  172.     if (!ind) {    /* special case if no previous indentation */
  173.         if (top_indent(prev_end, prev2_end))
  174.             ind += INCR;
  175.     } else if (prev_end == ';') {
  176.         if (!index(";{}", prev2_end))
  177.             ind -= INCR;
  178.     } else if (prev_end == '}') {
  179.         if (!Closeback)
  180.             ind -= INCR;
  181.     } else if (prev_end != '{' || index(";{}", prev2_end)
  182.                         || c_statement_start())
  183.         ind += INCR;
  184.     /* otherwise, last is probably continuation of a stmt or func decl */
  185.     if (Closeback && first_char == '}')
  186.         ind -= INCR;
  187.     point = orig;
  188.     return ind;
  189. }
  190.  
  191. /*  Look at the last two lines and guess at the correct indentation,
  192.     assuming C source (or similar).  If we're not in this line's
  193.     indentation, though, or our new indentation matches the old,
  194.     just insert a tab.
  195. */
  196.  
  197. c_indent() on c_tab['\t']
  198. {
  199.     int orig = point;
  200.     int orig_column = current_column();
  201.  
  202.     to_indentation();
  203.     if (orig_column > current_column()) {    /* if not in indentation */
  204.         point = orig;
  205.         insert('\t');            /* insert a tab */
  206.     } else if (prev_cmd == C_INDENT)    /* repeated, make bigger */
  207.         to_column(orig_column + INCR);
  208.     else
  209.         to_column(c_compute_indent());
  210.     this_cmd = C_INDENT;
  211. }
  212.  
  213. /*
  214. Tell if more indent is required.
  215. Assumes last line had no indent and point is at its start.
  216. The hard case is distinguishing between these when Topindent is zero:
  217.  
  218.     foo();                foo();
  219. }                }
  220. func(bar)            if (bar)
  221.  
  222. When point is just after these examples, we must examine the word
  223. at "func" to distinguish the left example (the end of a function and
  224. beginning of the next, requiring no indentation) from the right (the
  225. end of a block and start of a conditional, requiring indentation).
  226. */
  227. top_indent(prev_end, prev2_end)
  228. {
  229. int ret;
  230.  
  231. if (Topindent)
  232.     ret = prev_end == '{';
  233. else if (ret = !index(";}", prev_end) && index(";{}", prev2_end))
  234.     if (prev_end != '{' && !c_statement_start())
  235.         ret = 0;
  236. return ret;
  237. }
  238.  
  239. /*
  240. Tell if the last line begins a statement (rather than a function
  241. declaration or the continuation of a previous statement).
  242. Assumes point is at the start of the last line.
  243. */
  244. c_statement_start()
  245. {
  246. return parse_string(1, "[{} \t]*(if|else|while|do|for)[^a-zA-Z0-9]",
  247.     (char *) 0);
  248. }
  249.  
  250. /*  fix indentation if necessary when } is typed */
  251. c_close() on c_tab['}']
  252. {
  253.     int orig = point;
  254.     int orig_column;        /* point's column */
  255.     int ind;
  256.  
  257.     if (Closeback) {
  258.         orig_column = current_column();
  259.         to_indentation();
  260.         ind = current_column();        /* get line's indentation */
  261.         point = orig;
  262.         if (orig_column <= ind)        /* if in indentation */
  263.             to_column(ind - INCR);
  264.     }
  265.     if (Matchdelim)
  266.         show_matching_delimiter();
  267.     else
  268.         normal_character();
  269. }
  270.